package com.tdd;

import org.I0Itec.zkclient.ZkClient;
import org.I0Itec.zkclient.exception.ZkNodeExistsException;
import org.I0Itec.zkclient.serialize.BytesPushThroughSerializer;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * @author tudedong
 * @description
 * @date 2020-07-11 14:42:54
 */
public class IdGenerator {

    private ZkClient zkClient = null;
    //zk地址
    private final String server;
    //父节点路径
    private final String root;
    //节点的名称
    private final String nodeName;

    private volatile boolean running = false;

    private ExecutorService cleanExector = null;

    /**
     * 删除节点的级别
     */
    public enum RemoveMethod{
        NONE,IMMEDIATELY,DELAY

    }

    public IdGenerator(String zkServer,String root,String nodeName){
        this.root = root;
        this.server = zkServer;
        this.nodeName = nodeName;

    }

    public void start() throws Exception {
        if (running){
            throw new Exception("zk服务已启动，，，");
        }
        running = true;
        init();
    }


    public void stop() throws Exception {
        if (!running){
            throw new Exception("zk服务已停止，，，");
        }
        running = false;
        freeResource();
    }

    /**
     * 初始化服务资源
     */
    private void init(){

        zkClient = new ZkClient(server,50000,50000,new BytesPushThroughSerializer());
        cleanExector = Executors.newFixedThreadPool(10);
        try{
            zkClient.createPersistent(root,true);
        }catch (ZkNodeExistsException e){
           //服务初始化失败
        }

    }

    /**
     * 释放服务资源
     */
    private void freeResource(){

        cleanExector.shutdown();
        try{
            cleanExector.awaitTermination(2, TimeUnit.SECONDS);

        }catch(InterruptedException e){
            e.printStackTrace();
        }finally{
            cleanExector = null;
        }

        if (zkClient != null){
            zkClient.close();
            zkClient=null;

        }
    }

    /**
     * 检测服务是否正在运行
     * @throws Exception
     */
    private void checkRunning() throws Exception {
        if (!running) {
            throw new Exception("请先调用start()");
        }
    }

    private String ExtractId(String str){
        int index = str.lastIndexOf(nodeName);
        if (index >= 0){
            index+=nodeName.length();
            return index <= str.length()?str.substring(index):"";
        }
        return str;

    }

    /**
     * 生产ID
     * @param removeMethod 删除的方法
     * @return
     * @throws Exception
     */
    public String generateId(RemoveMethod removeMethod) throws Exception{
        checkRunning();
        //构造顺序节点的完整路径
        final String fullNodePath = root.concat("/").concat(nodeName);
        //创建持久化顺序节点
        final String ourPath = zkClient.createPersistentSequential(fullNodePath, null);
        //避免zookeeper的顺序节点暴增，直接删除掉刚创建的顺序节点
        if (removeMethod.equals(RemoveMethod.IMMEDIATELY)){
            zkClient.delete(ourPath);
            //延迟删除
        }else if (removeMethod.equals(RemoveMethod.DELAY)){
            //用线程池执行删除，让generateId()方法尽快返回
            cleanExector.execute(new Runnable() {
                @Override
                public void run() {
                    zkClient.delete(ourPath);
                }
            });

        }
        //node-0000000000, node-0000000001，ExtractId提取ID
        return ExtractId(ourPath);
    }
}
